package com.rmy.queue.common.webSocket;

import com.alibaba.fastjson2.JSON;
import com.rmy.common.core.text.Convert;
import com.rmy.common.utils.spring.SpringUtils;
import com.rmy.queue.common.webSocket.domain.ProjectWebSocket;
import com.rmy.queue.domain.QmsWindowInfo;
import com.rmy.queue.service.IQmsWindowInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.CrossOrigin;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;


/**
 * @ClassName : WebSocketServer
 * @Description : WebSocket服务
 * @Date: 2020-05-29 15:41
 */
@ServerEndpoint(value = "/websocket/queue/{userName}/{windowUuid}", configurator = WebSocketConfigurator.class)
@Component
@CrossOrigin
public class ProjectWebSocketServer {

    private static Logger logger = LoggerFactory.getLogger(ProjectWebSocketServer.class);

    /**
     * 静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。
     */
    private static int projectOnlineCount = 0;
    /**
     * concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。
     */
    public static ConcurrentHashMap<String, ProjectWebSocketServer> projectWebSocketMap = new ConcurrentHashMap<>();

    public static ConcurrentHashMap<String, String> mapUserWindow = new ConcurrentHashMap<>();

    public Session getSession() {
        return session;
    }

    public void setSession(Session session) {
        this.session = session;
    }

    /**
     * 与某个客户端的连接会话，需要通过它来给客户端发送数据
     */
    private Session session;

    public static String projectWebSocketOnLineCount = "ONLINE_COUNT";

    /**
     * 接收userName
     */
    private String userName = "";

    private IQmsWindowInfoService qmsWindowInfoService = getQmsWindowInfoService();

    private IQmsWindowInfoService getQmsWindowInfoService() {
        if (qmsWindowInfoService != null) {
            return qmsWindowInfoService;
        }else {
            synchronized (this){
                return SpringUtils.getBean(IQmsWindowInfoService.class);
            }
        }
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("userName") String userName, @PathParam("windowUuid") String windowUuid) {
        Map<String, Object> userProperties = session.getUserProperties();
        String ipAddr = Convert.toStr(userProperties.get(WebSocketConfigurator.IP_ADDR));
        logger.info("客户端IP:"+ipAddr);
        this.session = session;
        this.userName = userName;
        QmsWindowInfo qmsWindowInfo = new QmsWindowInfo();
        qmsWindowInfo.setUuid(windowUuid);
        qmsWindowInfo.setRunningStatus("2");
        qmsWindowInfoService.updateQmsWindowInfoByUuid(qmsWindowInfo);
        mapUserWindow.put(userName, windowUuid);
        if (projectWebSocketMap.containsKey(this.userName)) {
            // 关闭socket（强制下线）
            try {
                projectWebSocketMap.get(this.userName).getSession().close();
            } catch (IOException e) {
                e.printStackTrace();
            }

            projectWebSocketMap.remove(this.userName);
            projectWebSocketMap.put(this.userName, this);
            //加入set中
        } else {
            projectWebSocketMap.put(this.userName, this);
//            addOnlineCount(type);
            //加入set中
        }
    }

    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose( @PathParam("userName") String userName, @PathParam("windowUuid") String windowUuid) {
        this.userName = userName;
        QmsWindowInfo qmsWindowInfo = new QmsWindowInfo();
        qmsWindowInfo.setUuid(windowUuid);
        qmsWindowInfo.setRunningStatus("1");
        qmsWindowInfoService.updateQmsWindowInfoByUuid(qmsWindowInfo);
        if (projectWebSocketMap.containsKey(this.userName)) {
            projectWebSocketMap.remove(this.userName);
            //从set中删除
//            subOnlineCount(type);
            logger.info("用户退出:" + this.userName + ",当前在线人数为:" + getProjectOnlineCount());
        }
        mapUserWindow.remove(userName);


//        LoginUser loginUser = SecurityAuthorityUtils.getLoginUser();
//        this.userName = loginUser.getUsername();
//        log.info("用户退出失败:" + this.userName + ",当前在线人数为:" + getProjectOnlineCount());
    }

    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息
     */
    @OnMessage
    public void onMessage(String message, @PathParam("userName") String userName, @PathParam("windowUuid") String windowUuid) {
    }

    /**
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
//        log.error("用户错误:" + this.userName + ",原因:" + error.getMessage());
        error.printStackTrace();
    }

    /**
     * 实现服务器主动推送
     */
    public static void sendMessage(ProjectWebSocket message) throws IOException {
        projectWebSocketMap.get(message.getName()).getSession().getBasicRemote().sendText(JSON.toJSONString(message));
    }

    /**
     * 发送到指定的窗口
     * @param targetWindowUuids 逗号分割字符串
     * @param message
     * @throws IOException
     */
    public static void sendTargetMessage(String targetWindowUuids, String message) throws IOException {
        logger.info("发送目标窗口："+targetWindowUuids);
        String[] arrWindow = targetWindowUuids.split(",");
        for (Map.Entry<String, String> entry : mapUserWindow.entrySet()) {
            for (int x = 0; x < arrWindow.length; x++){
                // 窗口ID相等
                if (arrWindow[x].equals(entry.getValue())) {
                    projectWebSocketMap.get(entry.getKey()).getSession().getBasicRemote().sendText(message);
                    break;
                }
            }
        }

    }

//    /**
//     * 实现服务器主动推送
//     */
//    public void sendMessage(String message, String userName) throws IOException {
//
////        WebSocketServer webSocketServer = redisCache.hget(connectUser, userName);
////        this.session.getBasicRemote().sendText(message);
//
//        webSocketMap.get(userName).getSession().getBasicRemote().sendText(message);
//    }
//    /**
//     * 实现服务器主动推送
//     */
//    public void sendMessage(String message) throws IOException {
////        webSocketServer.getSession().getBasicRemote().sendText(message);
//
//        for (Map.Entry<String, WebSocketServer> entry : webSocketMap.entrySet()) {
//            System.out.println("【websocket消息】广播消息:" + message);
//            try {
//                entry.getValue().session.getAsyncRemote().sendText(message);
//            } catch (Exception e) {
//                e.printStackTrace();
//            }
//        }
//    }

    // 此为广播消息
    public static void sendAllMessage(String message) {
        for (Map.Entry<String, ProjectWebSocketServer> entry : projectWebSocketMap.entrySet()) {
            System.out.println("【websocket消息】广播消息:" + message);
            try {
                entry.getValue().session.getAsyncRemote().sendText(message);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 发送自定义消息
     */
//    public void sendInfo(String message, String userName) throws IOException {
//        log.info("发送消息到:" + userName + "，报文:" + message);
//        if (StringUtils.isNotBlank(userName) && webSocketMap.containsKey(userName)) {
//            sendMessage(message, userName);
//        } else {
//            log.error("用户" + userName + ",不在线！");
//        }
//    }

    public  int getProjectOnlineCount() {
        return projectWebSocketMap.size();
    }

    public void addOnlineCount(String type) {
//        redisCache.setCacheSet(webSocketMapRedisKey, webSocketMap.keySet());
//        redisCache.zincrementScore(type.toUpperCase()+":"+projectWebSocketOnLineCount,type,1);

    }

    public  void subOnlineCount(String type) {
//        redisCache.setCacheSet(webSocketMapRedisKey, webSocketMap.keySet());
//        redisCache.zincrementScore(type.toUpperCase()+":"+projectWebSocketOnLineCount,type,-1);
    }


}
